package com.loongtech.bi.support;

import com.loongtech.bi.action.realTime.BossRealTimeAction;
import com.loongtech.bi.action.realTime.PlatformAndChannelRealTimeAction;
import com.loongtech.core.util.Time;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.message.BasicNameValuePair;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;

/**
 * 异步http类
 *
 * @author Marin
 */
public class AsyncHttpClientUtils {
	private static final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();

	public static long allActiveDataTime = 0L;
	public static long allPlatformDataTime = 0L;
	public static long paltformDataTime = 0L;
	public static long channelDataTime = 0L;

	/**
	 * 异步发送http请求
	 *
	 * @param url
	 */
	public static void asyncSendAllActiveDataRequest(final BossRealTimeAction action, final String url) {
		if ((Time.currentTime() - allActiveDataTime) / Time.MIN < 2 || null == action) {
			System.out.println("查询太频繁");
			return;
		} else {
			allActiveDataTime = Time.currentTime();
		}

		if (url == null || "".equals(url)) {
			System.out.println("url is null");
			return;
		}

		final CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();
		httpclient.start();
		final HttpGet request = new HttpGet(url);
		httpclient.execute(request, new FutureCallback<HttpResponse>() {

			@Override
			public void completed(final HttpResponse response) {
				try {
					InputStream is = response.getEntity().getContent();
					action.setActivateData(getStreamAsString(is, StandardCharsets.UTF_8.name()));
				} catch (IOException e) {
					e.printStackTrace();
				}

				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("completed___" + request.getRequestLine() + "->" + response.getStatusLine());
			}

			@Override
			public void failed(final Exception ex) {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("failed____" + request.getRequestLine() + "->" + ex);
			}

			@Override
			public void cancelled() {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("cancelled___" + request.getRequestLine() + " cancelled");
			}
		});
	}

	/**
	 * 异步发送http请求
	 *
	 * @param url
	 */
	public static void asyncSendAllPlatformActiveDataRequest(final String url, final String ds) {
		if ((Time.currentTime() - allPlatformDataTime) / Time.MIN < 2) {
			System.out.println("查询太频繁");
			return;
		} else {
			allPlatformDataTime = Time.currentTime();
		}

		if (url == null || "".equals(url)) {
			System.out.println("url is null");
			return;
		}

		final CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();
		httpclient.start();
		final HttpGet request = new HttpGet(url);
		httpclient.execute(request, new FutureCallback<HttpResponse>() {

			@Override
			public void completed(final HttpResponse response) {
				try {
					InputStream is = response.getEntity().getContent();
					PlatformAndChannelRealTimeAction.activateAllPlatformData.put(ds, getStreamAsString(is, StandardCharsets.UTF_8.name()));
				} catch (IOException e) {
					e.printStackTrace();
				}

				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("completed___" + request.getRequestLine() + "->" + response.getStatusLine());
			}

			@Override
			public void failed(final Exception ex) {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("failed____" + request.getRequestLine() + "->" + ex);
			}

			@Override
			public void cancelled() {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("cancelled___" + request.getRequestLine() + " cancelled");
			}
		});
	}

	/**
	 * 异步发送http请求
	 *
	 * @param url
	 */
	public static void asyncSendPlatformActiveDataRequest(final String url, final String ds) {
		if ((Time.currentTime() - paltformDataTime) / Time.MIN < 2) {
			System.out.println("查询太频繁");
			return;
		} else {
			paltformDataTime = Time.currentTime();
		}

		if (url == null || "".equals(url)) {
			System.out.println("url is null");
			return;
		}

		final CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();
		httpclient.start();
		final HttpGet request = new HttpGet(url);
		httpclient.execute(request, new FutureCallback<HttpResponse>() {

			@Override
			public void completed(final HttpResponse response) {
				try {
					InputStream is = response.getEntity().getContent();
					String ssss = getStreamAsString(is, StandardCharsets.UTF_8.name());

					if (ssss != null && !"".equals(ssss)) {
						ssss = ssss.replaceAll("\\{", "").replaceAll("\\}", "").replaceAll("\"", "");
						Map<String, String> tmp = PlatformAndChannelRealTimeAction.activatePlatformData.get(ds);
						if (tmp == null) {
							tmp = new HashMap<>();
							PlatformAndChannelRealTimeAction.activatePlatformData.put(ds, tmp);
						}
						String[] sss = ssss.split(",");
						for (String ss : sss) {
							String[] s = ss.split(":");
							tmp.put(s[0], s[1]);
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}

				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("completed___" + request.getRequestLine() + "->" + response.getStatusLine());
			}

			@Override
			public void failed(final Exception ex) {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("failed____" + request.getRequestLine() + "->" + ex);
			}

			@Override
			public void cancelled() {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("cancelled___" + request.getRequestLine() + " cancelled");
			}
		});
	}

	 public static void main(String[] args) {
	 String s =
	 "{13:4142,21:261,31:188,43:4091,53:6621,63:428,71:2,73:3,83:10308,93:3774,113:5772,193:24,202:3824,203:1044,213:928,223:297,233:1037,243:806,253:396,263:783,273:232,283:12353,291:21,301:233,313:2304,321:36,323:34,333:2156,351:139,353:137,373:4,383:6,393:106,403:14,413:9,423:466,433:4,443:29,453:49,463:71,473:108,493:617,503:122}";
	 String ss = "{\"3\":\"52473\",\"2\":\"3187\",\"1\":\"758\"}";
	
	 s=s.replaceAll("\\{", "");
	 s=s.replaceAll("\\}", "");
	 s=s.replaceAll("\"", "");
	
	 ss= ss.replaceAll("\\{", "");
	 ss= ss.replaceAll("\\}", "");
	 ss= ss.replaceAll("\"", "");
	
	 System.out.println(s);
	 System.out.println(ss);
	
	 }

	/**
	 * 异步发送http请求
	 *
	 * @param url
	 */
	public static void asyncSendChannelActiveDataRequest(final String url, final String ds) {
		if ((Time.currentTime() - channelDataTime) / Time.MIN < 2) {
			System.out.println("查询太频繁");
			return;
		} else {
			channelDataTime = Time.currentTime();
		}

		if (url == null || "".equals(url)) {
			System.out.println("url is null");
			return;
		}

		final CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();
		httpclient.start();
		final HttpGet request = new HttpGet(url);
		httpclient.execute(request, new FutureCallback<HttpResponse>() {

			@Override
			public void completed(final HttpResponse response) {
				try {
					InputStream is = response.getEntity().getContent();
					String ssss = getStreamAsString(is, StandardCharsets.UTF_8.name());
					if (ssss != null && !"".equals(ssss)) {
						Map<String, String> tmp = PlatformAndChannelRealTimeAction.activateChannelData.get(ds);
						if (tmp == null) {
							tmp = new HashMap<>();
							PlatformAndChannelRealTimeAction.activateChannelData.put(ds, tmp);
						}

						ssss = ssss.replaceAll("\\{", "").replaceAll("\\}", "").replaceAll("\"", "");
						String[] sss = ssss.split(",");
						for (String ss : sss) {
							String[] s = ss.split(":");
							tmp.put(s[0], s[1]);
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}

				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("completed___" + request.getRequestLine() + "->" + response.getStatusLine());
			}

			@Override
			public void failed(final Exception ex) {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("failed____" + request.getRequestLine() + "->" + ex);
			}

			@Override
			public void cancelled() {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.out.println("cancelled___" + request.getRequestLine() + " cancelled");
			}
		});
	}

	private static String getStreamAsString(InputStream stream, String charset) throws IOException {
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(stream, charset), 8192);
			StringWriter writer = new StringWriter();

			char[] chars = new char[8192];
			int count = 0;
			while ((count = reader.read(chars)) > 0) {
				writer.write(chars, 0, count);
			}

			return writer.toString();
		} finally {
			if (stream != null) {
				stream.close();
			}
		}
	}

	// 服务器启动时，给biroot发信息
	public static void cidRestart(String url) {
		if (StringUtils.isNotEmpty(url)) {
			final CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();
			httpclient.start();
			final HttpGet request = new HttpGet(url);
			httpclient.execute(request, new FutureCallback<HttpResponse>() {

				@Override
				public void completed(final HttpResponse response) {
					try {
						httpclient.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					System.out.println("服务器启动时，给biroot发信息成功");
				}

				@Override
				public void failed(final Exception ex) {
					try {
						httpclient.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					System.out.println("服务器启动时，给biroot发信息失败");
				}

				@Override
				public void cancelled() {
					try {
						httpclient.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					System.out.println("服务器启动时，给biroot发信息失败：请求被删除");
				}
			});
		} else {
			System.out.println("服务器启动时，给biroot发信息失败：url为空");
		}
	}

	/**
	 * 异步Http请求(get方式)
	 * @param url
	 * @param params
	 * @throws IOException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 */
	public static void asyncSendHttpGetRequest(String url, Map<String, Object> params) throws IOException, InterruptedException, ExecutionException {
		if (url == null || "".equals(url)) {
			System.out.println("url is null");
			return;
		}
		if (params == null)
			params = new HashMap<>();
		// 拼接参数
		StringBuilder urlSB = new StringBuilder();
		for (Entry<String, Object> entry : params.entrySet()) {
			Object value = entry.getValue();
			String v = (value == null) ? "" : URLEncoder.encode(entry.getValue().toString(), "UTF-8");
//			String v = (value == null) ? "" : entry.getValue().toString();
			urlSB.append(entry.getKey()).append("=").append(v).append("&");
		}
		String urlStrFinal = params.isEmpty() ? url : url + "?" + urlSB.deleteCharAt(urlSB.length() - 1);
		
		System.out.println("url:" + urlStrFinal);
		
		// 请求地址
		final HttpGet request = new HttpGet(urlStrFinal.trim());
		
		// 设置超时时间为3s
		RequestConfig config = RequestConfig.custom().setSocketTimeout(3000).setAuthenticationEnabled(false).setConnectTimeout(3000).build();
		CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(config).build();
		try {
			httpclient.start();
			final CountDownLatch latch = new CountDownLatch(1);
			httpclient.execute(request, new FutureCallback<HttpResponse>() {
				@Override
				public void completed(final HttpResponse response) {

					InputStream in;
					BufferedReader reader;
					try {
						in = response.getEntity().getContent();
						reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
						StringBuilder sb = new StringBuilder();
						String line = null;
						while ((line = reader.readLine()) != null) {
							sb.append(line);
						}
						System.out.println("接口返回值为:" + sb.toString());
					} catch (UnsupportedOperationException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
					latch.countDown();
					System.out.println("completed___" + request.getRequestLine() + "->" + response.getStatusLine());
				}

				@Override
				public void failed(final Exception ex) {
					latch.countDown();
					System.out.println("failed____" + request.getRequestLine() + "->" + ex);
				}

				@Override
				public void cancelled() {
					latch.countDown();
					System.out.println("cancelled___" + request.getRequestLine() + " cancelled");
				}
			});
			latch.await();
			System.out.println("Shutting down");
		} finally {
			httpclient.close();
			System.out.println("done！");
		}
	}
	
	private static String format(Object obj){
		return null != obj ? obj.toString() : null;
	}


    /**
     * 异步Http请求(post方式)
     * @param url
     * @param params
     * @throws IOException
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public static void asyncSendHttpPostRequest(String url, Map<String, Object> params) throws IOException, InterruptedException, ExecutionException {
        if (url == null || "".equals(url)) {
            System.out.println("url is null");
            return;
        }
        final HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> list = new ArrayList<>();
        Iterator<Entry<String, Object>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()){
            Entry<String,Object> elem = iterator.next();
            System.out.println("*************************************** 参数" + elem.getKey() + "的值为:" + elem.getValue());
            list.add(new BasicNameValuePair(elem.getKey(),format(elem.getValue())));
        }

        // 请求地址
        if(list.size() > 0){
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,"UTF-8");
            httpPost.setEntity(entity);
        }
        System.out.println("POST 请求...." + httpPost.getURI());
        // 设置超时时间为3s
        RequestConfig config = RequestConfig.custom().setSocketTimeout(3000).setAuthenticationEnabled(false).setConnectTimeout(3000).build();
        CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setDefaultRequestConfig(config).build();
        try {
            httpclient.start();
            final CountDownLatch latch = new CountDownLatch(1);
            httpclient.execute(httpPost, new FutureCallback<HttpResponse>() {
                @Override
                public void completed(final HttpResponse response) {

                    InputStream in;
                    BufferedReader reader;
                    try {
                        in = response.getEntity().getContent();
                        reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
                        StringBuilder sb = new StringBuilder();
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                            sb.append(line);
                        }
                        System.out.println("接口返回值为:" + sb.toString());
                    } catch (UnsupportedOperationException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    latch.countDown();
                    System.out.println("completed___" + httpPost.getRequestLine() + "->" + response.getStatusLine());
                }

                @Override
                public void failed(final Exception ex) {
                    latch.countDown();
                    System.out.println("failed____" + httpPost.getRequestLine() + "->" + ex);
                }

                @Override
                public void cancelled() {
                    latch.countDown();
                    System.out.println("cancelled___" + httpPost.getRequestLine() + " cancelled");
                }
            });
            latch.await();
            System.out.println("Shutting down");
        } finally {
            httpclient.close();
            System.out.println("done！");
        }
    }
}